#pragma once

#include "TcpServer.hpp"
#include "Http_agre.hpp"

class HttpServer
{
    static const uint16_t default_port = 0;

    typedef function<void(const HttpRequest &, HttpResponse &)> Business_t;

    bool isComplete(string &inbuf, string &sk) // 判断报文是否完整，如果完整就取出一份放进sk中
    {
        LOG(LogLevel::DEBUG) << "进入HttpServer: isComplete";

        // 判断请求行释放完整
        int request_line_end = inbuf.find(default_request_header_sep);
        if (request_line_end == string::npos) // 如果请求行不完整
        {
            LOG(LogLevel::DEBUG) << "请求行不完整";
            return false;
        }

        // 判断请求报头是否完整，即是否能读取到空行
        int request_header_end = inbuf.find(default_request_header_sep + default_blank_line);
        if (request_header_end == string::npos)
        {
            LOG(LogLevel::DEBUG) << "请求报头不完整";
            return false;
        }
        // 判断请求正文是否完整
        // 根据协议，只能通过请求报头中的字段:Content_Lenth判断
        // 如果没有Content_Lenth字段，就视为没有请求正文
        string str = "Content-Length:";
        int start = inbuf.find(str);
        int sep_size = (default_request_header_sep + default_blank_line).size();
        if (start != string::npos) // 如果找到了"Content_Lenth:"
        {
            int end = inbuf.find("\r\n", start);
            int body_size = stoi(inbuf.substr(start + str.size(), end - start));

            LOG(LogLevel::DEBUG) << "body_size " << body_size;

            if ((inbuf.size() - (request_header_end + sep_size)) < body_size)
            {
                LOG(LogLevel::DEBUG) << "请求正文不完整";
                return false;
            }

            // 从用户级接收缓冲区中取出一份报文
            sk = inbuf.substr(0, request_header_end + sep_size + body_size);

            // 从用户级接收缓冲区中删除被取走的报文
            inbuf.erase(0, request_header_end + sep_size + body_size);
            return true;
        }
        LOG(LogLevel::DEBUG) << "没有请求正文";

        // 从用户级接收缓冲区中取出一份报文
        sk = inbuf.substr(0, request_header_end + sep_size);
        // 从用户级接收缓冲区中删除被取走的报文
        inbuf.erase(0, request_header_end + sep_size);

        return true;
    }
    string HandleRequest(string &inbuf)
    {
        string sk;//一份完整报文

        string outbuf;//返回值

        while (isComplete(inbuf, sk))
        {
            // 拿到一份完整报文
            LOG(LogLevel::DEBUG) << "成功获取一份完整的请求报文";
            // 反序列化request
            HttpRequest requ;
            requ.Deserialization(sk);//反序列化

            // debug
            requ.Print();

            // 根据request构建response
            HttpResponse resp;
            _business(requ, resp);

            // debug
            resp.Print();

            // 序列化response
            string tmp;
            resp.Serialization(tmp);//序列化

            outbuf += tmp;
            sk.clear();
        }

        return outbuf;
    }

public:
    HttpServer(uint16_t port = default_port)
        : _port(port),
          _tcp_server(make_unique<TcpServer>(port)),
          _business(nullptr)
    {
        _tcp_server->Registered([this](string &inbuf)
                                { return this->HandleRequest(inbuf); });
    }
    void Registered(Business_t hand)
    {
        _business = hand;
    }
    void Start()
    {
        LOG(LogLevel::DEBUG) << "HttpServer启动";
        _tcp_server->Start();
    }
    void Stop()
    {
        _tcp_server->Stop();
    }

private:
    uint16_t _port;
    unique_ptr<TcpServer> _tcp_server;
    Business_t _business;
};